﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Battle;
using Item.Buff;
using LitJson;
using UnityEngine;
using UnityEngine.AddressableAssets;

namespace ItemComponent
{
    public abstract class AreaItemComponent:MyItemComponentMono,IAreaTriggerHandler
    {
        #region 生成预制
        protected const string AreaPrefabKey = "Area_";
        protected static async Task<Area> CreateAreaAsync(string prefabName)
        {
            if (string.IsNullOrEmpty(prefabName))
                prefabName = "Normal";
            GameObject prefab = await Addressables.LoadAssetAsync<GameObject>(AreaPrefabKey + prefabName).Task;
            var obj = Instantiate(prefab);
            Area area = obj.GetComponent<Area>();
            if (area == null) area = obj.AddComponent<Area>();
            return area;
        }
        #endregion

        protected const string Key_AreaData = "AreaData";

#if UNITY_EDITOR
        [SerializeField, ReadOnly]
        private ST_AreaData debugAreaData;
#endif

        public ST_AreaData AreaData { get; protected set; }
        public ST_AreaData CurAreaData { get; protected set; }

        protected Area objArea;
        protected Vector3 vAreaMoveTarget;

        protected bool isDeath = false;

        private void Awake()
        {
            this.enabled = false;
        }

        public override async void InitComponent(JsonData data, Item.ItemBase item)
        {
            if (data == null || data[Key_AreaData] == null) return;

            ST_AreaData tmp = JsonMapper.ToObject<ST_AreaData>(data[Key_AreaData].ToJson());

            AreaData = tmp;
            CurAreaData = tmp;
#if UNITY_EDITOR
            debugAreaData = tmp;
#endif

            vAreaMoveTarget = Vector3.zero;
            RefreshTargetAsync();
            await InitAreaAsync();
        }

        protected virtual async Task InitAreaAsync()
        {
            objArea = await CreateAreaAsync(AreaData.strAreaPrefabName);

            //避免异步之后，该组件已经被删了
            if (isDeath)
            {
                Destroy(objArea.gameObject);
                return;
            }

            objArea.InitArea(CurAreaData.rangeData, this);
            objArea.transform.position = transform.position;
            objArea.gameObject.SetActive(false);
        }

        protected virtual async void RefreshTargetAsync()
        {
            while (!isDeath)
            {
                var target = EnemyMgr.Ins.GetTarget(transform.position);
                if (target != null)
                    vAreaMoveTarget = target.Pos;

                await Task.Delay(500);
            }
        }

        protected virtual void Update()
        {
            if (objArea != null)
                objArea.transform.position = Vector3.Lerp(objArea.transform.position, vAreaMoveTarget, (float)CurAreaData.dAreaMoveSpeed * Time.deltaTime);
        }

        public override void OnBuffChange(STBuffEffectData buffEffectData)
        {
            var tmpData = AreaData;

            tmpData.dAreaMoveSpeed *= buffEffectData.fSpeed;
            tmpData.rangeData.dRadius *= buffEffectData.fRange;

            if (objArea != null)
                objArea.InitArea(tmpData.rangeData, this);

            CurAreaData = tmpData;
        }

        private void OnEnable()
        {
            if (objArea != null)
                objArea.gameObject.SetActive(true);
        }
        private void OnDisable()
        {
            if (objArea != null)
                objArea.gameObject.SetActive(false);
        }
        protected virtual void OnDestroy()
        {
            isDeath = true;

            if (objArea != null)
                Destroy(objArea.gameObject);
        }

        public abstract void OnEnter2D(Collider2D target);

        public abstract void OnExit2D(Collider2D target);

#if UNITY_EDITOR
        protected static STMyComponetData GetMyComponetData(ST_AreaData areaData)
        {
            JsonData json = new JsonData();
            json[Key_AreaData] = JsonMapper.ToObject(JsonMapper.ToJson(areaData));

            return new STMyComponetData()
            {
                data = json,
            };
        }
#endif
    }
}
